//
// Created by hjie on 23-6-22.
//
#include "websocket_server.h"
#include "config/config.h"
#include <uWS/Socket.h>
#include <uWS/Group.h>
#include "connection_data.h"

WebSocket::WebSocket()
{
    m_status = false;
}

WebSocket::~WebSocket() noexcept
{

}

void WebSocket::StopServer()
{
    m_status = false;
}

int WebSocket::StartListen(int port)
{
    m_hub.onConnection([this](uWS::WebSocket<uWS::SERVER> * socket, uWS::HttpRequest request){

        printf("new connect : %s:%d\n", socket->getAddress().address, socket->getAddress().port);
        m_connection_socket_map[socket->getFd()] = Connection{.m_socket = socket, .m_expire_time = m_count_timer};

    });
    m_hub.onDisconnection([this](uWS::WebSocket<uWS::SERVER> * socket, int code, char * msg, int size){

        printf("disconnect : %s:%d\n", socket->getAddress().address, socket->getAddress().port);
        void * user_data = socket->getUserData();
        if (user_data)
        {
            socket->setUserData(nullptr);
            auto connection = (ConnectionData*)user_data;
            connection->Destroy();
        }
        else
        {
            m_connection_socket_map.erase(socket->getFd());
        }
    });
    m_hub.onMessage([this](uWS::WebSocket<uWS::SERVER> * socket, char * msg, int size, int op_code){

        void * user_data = socket->getUserData();
        if (user_data)
        {
            // process user_data
            auto connection = ((ConnectionData*)user_data);
            connection->ProcessData(msg, size, op_code);
        }
        else
        {
            m_connection_socket_map.erase(socket->getFd());
            auto connection = new ConnectionData(nullptr);
            connection->m_socket = socket;
            socket->setUserData(connection);
            connection->ProcessData(msg, size, op_code);
        }
    });
    m_hub.onError([this](std::conditional<true, int, void *>::type error_code){


    });
    return 0;
}

void WebSocket::ProcessSocketMap()
{
    int64_t now_time = time(NULL);
    printf("socket map size : %ld\n", m_connection_socket_map.size());
    for (auto iter = m_connection_socket_map.begin(); iter != m_connection_socket_map.end(); )
    {
        auto use_iter = iter++;
        // ten second
        if (m_count_timer - use_iter->second.m_expire_time >= 10000)
        {
            m_connection_socket_map.erase(use_iter);
        }
    }
}

WebSocketServer::WebSocketServer()
{

}

WebSocketServer::~WebSocketServer() noexcept
{

}

int WebSocketServer::StartListen(int port)
{
    WebSocket::StartListen(port);
    m_hub.listen(Config::Instance()->GetListenPort());
    m_status = true;
    while(m_status)
    {
        m_hub.poll();
        m_count_timer++;
        if (m_count_timer % 1000000 == 0)
        {
            ProcessSocketMap();
        }
        usleep(1000);
    }
    return 0;
}

SSLWebSocketServer::SSLWebSocketServer()
{

}

SSLWebSocketServer::~SSLWebSocketServer() noexcept
{

}

int SSLWebSocketServer::StartListen(int port)
{
    auto config = Config::Instance();

    WebSocket::StartListen(port);
    //uS::TLS::Context ssl = uS::TLS::createContext("/home/hjie/download/ca/certs/valid_server_crt.pem", "/home/hjie/download/ca/certs/valid_server_key.pem");
    uS::TLS::Context c = uS::TLS::createContext("/home/hjie/source/uWebSockets/misc/ssl/cert.pem",
                                                "/home/hjie/source/uWebSockets/misc/ssl/key.pem",
                                                "1234");
    int ret = m_hub.listen(config->GetSSLListenPort(), c);
    //printf("ssl listen rest : %d\n", ret);
    m_status = true;
    while(m_status)
    {
        m_hub.poll();
        usleep(1000);
    }
    return 0;
}







